#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
#include <string>

#define THREAD_NUM 10    // 线程数量
int tickets = 100; // 票数

class ThreadDate
{
public:
    ThreadDate(const std::string &name, pthread_mutex_t* pmtx)
        : _name(name), _pmtx(pmtx)
    {
    }

public:
    std::string _name; // 线程名称
    pthread_mutex_t* _pmtx; // 互斥锁
};

void *getTicket(void *arg)
{
    ThreadDate *args = (ThreadDate *)arg;

    while (true)
    {
        pthread_mutex_lock(args->_pmtx); // 加锁
        if (tickets > 0)    
        {
            usleep(rand() % 100000 + 100000); // 模拟抢票耗时
            std::cout << args->_name << " ----> " << tickets-- << std::endl;

            pthread_mutex_unlock(args->_pmtx); // 解锁
        }
        else
        {
            pthread_mutex_unlock(args->_pmtx); // 解锁
            break;
        }

        usleep(rand() % 1000 + 100000); // 执行其它任务
    }

    delete args;

    return nullptr;
}

// 实现多线程抢票
int main()
{
    pthread_mutex_t mtx; // 创建互斥锁
    pthread_mutex_init(&mtx, nullptr); // 初始化互斥锁

    srand((unsigned int)time(nullptr)); // 随机种子

    pthread_t tids[THREAD_NUM]; // 线程tid

    // 创建线程
    for (size_t i = 0; i < THREAD_NUM; i++)
    {
        std::string name = "Thread: ";
        name += std::to_string(i);                                  // 线程名称
        ThreadDate *args = new ThreadDate(name, &mtx);                    // 构建参数对象
        pthread_create(tids + i, nullptr, getTicket, (void *)args); // 线程执行抢票任务
    }

    // 等待线程
    for (size_t i = 0; i < THREAD_NUM; i++)
    {
        pthread_join(tids[i], nullptr); // 回收线程
    }

    pthread_mutex_destroy(&mtx); // 销毁互斥锁

    return 0;
}